<?php
	/*
		CSS COMPRESSOR v1.0
		Usage:
			$cssToCompress = './path_of_file.css';
			echo CSSMin::compress($cssToCompress);
			
		Params:
			echo CSSMin::compress($cssToCompress[, boolean to show output in colors[, boolean to show stats in output]]);
			
		Original Idea:
			*//**
				CSS Compressor v0.9
				http://iceyboard.no-ip.org/projects/css_compressor
				Copyright (C) 2008 Robson
			**//*
			Thanks Robson!
			
		/-----------------------------------------------------------------------------------/
		|																												|
		|	This program is free software; you can redistribute it and/or							|
		|	modify it under the terms of the GNU General Public License								|
		|	as published by the Free Software Foundation; either version 2							|
		|	of the License, or (at your option) any later version.									|
		| 																												|
		|	This program is distributed in the hope that it will be useful,						|
		|	but WITHOUT ANY WARRANTY; without even the implied warranty of							|
		|	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the							|
		|	GNU General Public License for more details.													|
		| 																												|
		|	You should have received a copy of the GNU General Public License						|
		|	along with this program; if not, write to the Free Software								|
		|	Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.	|
		| 																												|
		/-----------------------------------------------------------------------------------/
	*/
	class CSSMin {
		protected $selectores		= Array();
		protected $propiedades		= Array();
		
		protected $output				= "";
		
		protected $curSelectores	= Array();
		protected $curPropiedades	= Array();
		protected $regla;
		protected $resultado			= "";
		
		/** Variables para estadisticas **/
		protected $tiempoInicio		= Array();
		protected $tiempoFin			= Array();
		
		/** Cantidad de caracteres del archivo original **/
		protected $tamanoInicial;
		
		/** Funciones Publicas **/
		public static function compress($css, $withColors = False, $mostrarResultados = False) {
			$cssMin = new CSSMin(implode('', file($css)));
			return $cssMin->comprimir($withColors, $mostrarResultados);
		}
		
		public function __construct($archivo) {
			$this->output = str_replace("\r\n","\n",$archivo);
			$this->tamanoInicial = strlen($this->output);
			$this->tiempoInicio = explode(' ', microtime());
		}
		
		/** Funciones Protegidas **/
		protected function comprimir($conColores, $estadisticas) {
			$this->remover2puntos();
			$this->sacarComentarios();
			/* eliminamos posibles espacios en blanco */
			$this->output = trim($this->output);
			/* cambiamos todo los valores RGB a HEX */
			$this->rgb2Hex();
			/* achicamos el tamano del los colores */
			$this->coloresLargosToHexCortos();
			$this->HexLargosToColoresCortos();
			/* Eliminamos las mediciones extra */
			$this->eliminarExtras();
			/* Separamos todas las propiedades y reglas */
			$this->ordenarCss();
			/* cambiamos el tamano de fuentes en texto a tamano en numeros */
			$this->tamanoTextoANumero();
			/* verificamos si hay selectores identicos y los combinamos */
			$this->combinarSelectoresIdenticos();
			/* eliminamos las propiedades que estan repetidas */
			$this->eliminarRepetidas();
			/* verificamos si las propiedades fueron combinadas */
			/* recorremos las propiedades en el archivo */
			for ($n = 0; $n < count($this->propiedades); $n++)
				/* intentamos combinar las diferentes partes */
				$this->combinarListaPropiedades($this->propiedades[$n]);
			/* recorremos las reglas del archivo */
			for ($n = 0; $n < count($this->propiedades); $n++)
				/* ejecutamos todas las propiedades para reducir su tamano */
				array_walk($this->propiedades[$n], 'reducirPropiedad');
			/* removemos todas las propiedades que se vaciaron anteriormente */
			$this->eliminarReglasVacias();
			/* verificamos si hay reglas iguales y eliminamos las primeras */
			$this->combinarReglasIdenticas();
			/* ejecutamos una ultima vez para remover todas las partes innecesarias de las matrices */
			$this->eliminarReglasVacias();
			/* creamos el resultado final */
			$this->crearSalida($conColores);
			$this->restaurar2puntos();
			$this->eliminarCorchetesVacios();
			if ($estadisticas)
				$this->mostrarResultados();
			return $this->resultado;
		}
		
		protected function mostrar() {
			$show = str_replace("\n\r","<BR />",$this->output);
			$show = str_replace("\n","<BR />",$show);
			$show = str_replace("\r","<BR />",$show);
			$show = str_replace("\t","&nbsp;&nbsp;&nbsp;&nbsp;",$show);
			echo $show . "<HR>";
		}
		
		protected function remover2puntos() {
			/* modificamos temporalmente los dos puntos en los enlaces */
			$this->output = str_replace('://', '[!semi-colon!]//', $this->output);
		}
		
		protected function sacarComentarios() {
			/* Eliminamos los comentarios HTML */
			$this->output = str_replace('<!--', '', $this->output);
			$this->output = str_replace('-->', '', $this->output);
			/* Eliminamos los comentarios CSS */
			$this->output = preg_replace('/\/\*(.*?)\*\//si', '', $this->output);
		}
		
		protected function rgb2Hex() {
			$text = "";
			/* recorremos mientras alla valores RGB en la cadena */
			while (strpos($this->output, 'rgb')) {
				/* ubicamos la primera posicion del valor RGB */
				$ubicacion = strpos($this->output, 'rgb');
				/* anadimos todo lo que hay antes del RGB en la cadena temporal */
				$text .= substr($this->output, 0, $ubicacion);
				/* eliminamos la parte inicial hasta la posicion de la cadena original */
				$this->output = substr($this->output, $ubicacion, strlen($this->output));
				/* buscamos el final del valor RGB */
				$ubicacion = strpos($this->output, ')');
				
				/* obtenemos el valor RGB, ejemplo: 'rgb(255, 170, 0)' */
				$valorRGB = substr($this->output, 0, $ubicacion + 1);
				
				/* removemos los posibles espacios, ejemplo: 'rgb(255,170,0)' */
				$valorRGB = eregi_replace(' +', '', $valorRGB);
				/* eliminamos las partes que no son valores, ejemplo: '255,170,0' */
				$valorRGB = substr($valorRGB, 4, -1);
				
				/* separamos los valores a un array, ejemplo: [255,170,0] */
				$valorRGB = explode(',', $valorRGB);
				
				/* seteamos la variable que almacenara el color con valor vacio para que no contenga datos viejos */
				$color = "";
				/* recorremos el array para obtener cada valor. El rojo, verde y azul */
				for ($n = 0; $n < 3; $n++)
					/* FF o 0F siempre retorna dos caracteres */
					$color .= strlen(dechex($valorRGB[$n])) == 1 ? '0' . dechex($valorRGB[$n]) : dechex($valorRGB[$n]);
					
				/* agregamos los seis caracteres y el valor hexadecimal a la cadena: ejemplo: '#FFAA00' */
				$text .= '#' . $color;
				/* eliminamos la propiedad RGB de la cadena original */
				$this->output = substr($this->output, $ubicacion + 1, strlen($this->output));
			}
			/*
				agregamos las partes restantes a la cadena original
				retornamos la nueva cadena con los valores RGB convertidos a HEX
			*/
			$this->output = $text . $this->output;
		}
		
		protected function coloresLargosToHexCortos() {
			/*
				cambiamos los colores largos a codigos HEX mas cortos
				ejemplo: fuscia -> #FF00FF (luego esto sera comprimido a '#F0F')
				primero, creamos un array con los colores largos y su valor HEX
				los valores HEX seran simplificados mas tarde
			*/
			$colores = array(
				array('000000', 'black'),
				array('ff00ff', 'fuchsia'),
				array('ffff00', 'yellow')
			);
			/* recorremos los colores */
			for ($n = 0; $n < count($colores); $n++)
				/* remplazamos todas las apariciones de los colores por el codigo HEX */
				$this->output = str_replace(":" . $colores[$n][1], ':#' . $colores[$n][0], $this->output);
		}
		
		protected function HexLargosToColoresCortos() {
			/*
				Aqui convertimos los valores HEX a un color mas pequeno equivalente
				Solo los dieciseis codigos de colores estandares son utilizados aqui.
				Los colores que son mas pequenos que su representacion HEX
			*/
			$colours = array(
				array('808080', 'gray'),
				array('008000', 'green'),
				array('800000', 'maroon'),
				array('00080', 'navy'),
				array('808000', 'olive'),
				array('800080', 'purple'),
				array('ff0000', 'red'),
				array('c0c0c0', 'silver'),
				array('008080', 'teal')
			);
			/* recorremos los colores */
			for ($n = 0; $n < count($colours); $n++)
				/* remplazamos el valor HEX con su nombre de color, ejemplo '#808080' -> 'gray' */
				$this->output = str_replace('#' . $colours[$n][0], $colours[$n][1], $this->output);
		}
		
		protected function eliminarExtras() {
			/*
				el cero es siempre cero, asi que los caracteres extras ('px', '%') no son necesarios
				modificamos los 0 ems, 0 pixeles, 0 porcentajes a 0
				esto no modifica los valores como podria hacerlo un valor como 10px sin su unidad 'px'
			*/
			$this->output = trim(eregi_replace('([^0-9])0(px|em|\%)', '\\10', ' ' . $this->output));
			$this->output = trim(eregi_replace('([^0-9])0\.([0-9]+)em', '\\1.\\2em', ' ' . $this->output));
		}
		
		protected function ordenarCss() {
			/*
				esta funcion separa el archivo CSS en reglas
				que luego son enviadas a otra funcion donde se ordena cada una de las partes
				lo primero que hay que hacer es separar toda la salida en el archivo
				asi que usaremos un buqle para recorrer todo el archivo
			*/
			while ($this->output !== False) {
				/* comprobamos si existe mas codigo */
				if (substr_count($this->output, '}')) {
					/* la siguiente regla es todo hasta el siguiente corchete */
					$this->regla = substr($this->output, 0, strpos($this->output, '}') + 1);
					/* separamos todo lo que hay en la regla actual */
					$this->separarRegla();
					/* eliminamos la regla del archivo CSS */
					$this->output = substr($this->output, strlen($this->regla), strlen($this->output));
				} else
					/* si no hay mas reglas asignamos False a la variable para que finalice el bucle */
					$this->output = False;
			}
		}
		
		protected function separarRegla() {
			/* obtenemos los selectores que contienen esta parte de la hoja */
			$selector = substr($this->regla, 0, strpos($this->regla, '{'));
			/* obtenemos las propiedades CSS y valores que figuran en esta parte de la hoja */
			$propiedad = trim(substr($this->regla, strlen($selector)+1, -1));
			
			/* removemos los espacios extras del selector */
			$this->limpiar($selector);
			/* removemos cualquier espacio adicional */
			$selector = trim(eregi_replace(', +', ',', $selector));
			$selector = trim(eregi_replace(' +,', ',', $selector));
			/* separamos el selector y lo agregamos al array de selectores */
			$this->selectores[] = array_unique(explode(',', $selector));
			
			/* ordenamos el codigo CSS */
			$this->limpiar($propiedad);
			/* removemos cualquier espacio adicional */
			$propiedad = trim(eregi_replace('(:|;) +', '\\1', $propiedad));
			$propiedad = trim(eregi_replace(' +(:|;)', '\\1', $propiedad));
			$propiedad = trim(eregi_replace('\( +', '(', $propiedad));
			$propiedad = trim(eregi_replace(' +\)', ')', $propiedad));
			/* si el ultimo caracter es un punto y coma lo removemos */
			if (substr($propiedad, strlen($propiedad)-1, 1) == ';')
				$propiedad = substr($propiedad, 0, -1);
			/* separamos las propiedades y las agregamos al array de propiedades */
			$this->propiedades[] = explode(';', $propiedad);
		}
		
		protected function limpiar(&$tipo) {
			/* eliminamos espacios en blanco, saltos de linea en la cadena */
			$tipo = str_replace(chr(10), '', $tipo);
			$tipo = str_replace(chr(13), '', $tipo);
			/* cambiamos los tabuladores por espacios */
			$tipo = str_replace(chr(9), ' ', $tipo);
			/* removemos espacios en blanco extras */
			$tipo = eregi_replace(' +', ' ', $tipo);
		}
		
		protected function tamanoTextoANumero() {
			/*
				cambiamos los tamanos de fuente establecidos en texto por numeros
				ejemplo: font-weight:normal -> font-weight : 400
			*/
			for ($a = 0; $a < count($this->propiedades); $a++) {
				for ($b = 0; $b < count($this->propiedades[$a]); $b++) {
					if ($this->propiedades[$a][$b] == 'font-weight:bold')
						$this->propiedades[$a][$b] = 'font-weight:700';
					if ($this->propiedades[$a][$b] == 'font-weight:normal')
						$this->propiedades[$a][$b] = 'font-weight:400';
					$this->propiedades[$a][$b] = str_replace('font:normal', 'font:400', $this->propiedades[$a][$b]);
					$this->propiedades[$a][$b] = str_replace('font:bold', 'font:700', $this->propiedades[$a][$b]);
				}
			}
		}
		
		protected function combinarSelectoresIdenticos() {
			/*
				el codigo siguiente combina las reglas en un selector unico
				si el valor actual esta en mas de un selector lo combina
				esto almacena todos los selectores que son usados
			*/
			/* recorremos todas las reglas */
			for ($a = 0; $a < count($this->selectores); $a++) {
				/* verificamos si este es un unico selector */
				if (count($this->selectores[$a]) == 1) {
					/* verificamos si este selector se utiliza despues */
					if (in_array($this->selectores[$a][0], $this->curSelectores)) {
						/* si se utiliza, recorremos hasta que encontremos donde */
						for ($b = 0; $b < count($this->curSelectores); $b++) {
							/* verificamos si este es igual a la regla anterior */
							if ($this->curSelectores[$b] == $this->selectores[$a][0]) {
								/*
									combinamos las propiedades en esta regla y la anterior
									continuan en el orden original del archivo, por lo que las nuevas sobreescriben
									a las viejas
								*/
								$new_props = array_merge($this->propiedades[$b], $this->propiedades[$a]);
								/* remplazamos la propiedad actual con todos las nuevas */
								$this->propiedades[$a] = $new_props;
								/* eliminamos el selector viejo */
								$this->selectores[$b] = NULL;
								/* eliminamos las propiedades viejas */
								$this->propiedades[$b] = array(NULL);
								/* lo eliminamos del array de selectores */
								$this->curSelectores[$b] = NULL;
							}
						}
					}
					/* agregamos el selector actual al array de selectores */
					$this->curSelectores[] = $this->selectores[$a][0];
				} else
					/* anadimos un valor nulo para mantener el indice de los selectores */
					$this->curSelectores[] = NULL;
			}
		}
		
		protected function eliminarRepetidas() {
			/*
				aqui eliminamos las clases duplicadas de las reglas
				si una propiedad esta repetida, solo la ultima se utiliza, todas las demas se eliminan
			*/
			/* recorremos las reglas */
			for ($a = 0; $a < count($this->propiedades); $a++) {
				/* esto guarda la lista de propiedades */
				$this->curPropiedades = array();
				/* recorremos todas las propiedades dentro de la regla actual */
				for ($b = 0; $b < count($this->propiedades[$a]); $b++) {
					/* separamos la propiedad y en valor */
					$parts = explode(':', $this->propiedades[$a][$b]);
					/* verificamos si esta propiedad esta usada previamente */
					if (in_array($parts[0], $this->curPropiedades)) {
						/* si esta, buscamos donde */
						for ($c = 0; $c < count($this->curPropiedades); $c++) {
							/* verificamos si esta es igual al anterior */
							if ($this->curPropiedades[$c] == $parts[0])
								/* eliminamos el anterior, este no se necesita */
								$this->propiedades[$a][$c] = NULL;
						}
					}
					/* agregamos el tipo al array de propuedades */
					$this->curPropiedades[] = $parts[0];
				}
			}
		}
		
		protected function combinarListaPropiedades($propiedadCombinar) {
			/*
				esta es la lista de propiedades que pueden ser combinadas
				el bucle envia la parte actual del estilo para trabajar aqui, combinar las propiedades
				y las pertes que componen esta propiedad
			*/
			$this->combinarPropiedad($propiedadCombinar, 'padding', array('padding-top', 'padding-right', 'padding-bottom', 'padding-left'));
			$this->combinarPropiedad($propiedadCombinar, 'margin', array('margin-top', 'margin-right', 'margin-bottom', 'margin-left'));
			$this->combinarPropiedad($propiedadCombinar, 'list-style', array('list-style-type', 'list-style-position', 'list-style-image'));
			$this->combinarPropiedad($propiedadCombinar, 'list-style', array('list-style-type', 'list-style-position'));
			$this->combinarPropiedad($propiedadCombinar, 'outline', array('outline-color', 'outline-style', 'outline-width'));
			
			/* esto es muy improbable */
			$this->combinarPropiedad($propiedadCombinar, 'background', array('background-color', 'background-image', 'background-repeat', 'background-attachment', 'background-position'));
			
			/* combinar todos los border-* ya que son lo mismo */
			$this->combinarPropiedad($propiedadCombinar, 'border-bottom', array('border-bottom-width', 'border-bottom-style', 'border-bottom-color'));
			$this->combinarPropiedad($propiedadCombinar, 'border-top', array('border-top-width', 'border-top-style', 'border-top-color'));
			$this->combinarPropiedad($propiedadCombinar, 'border-left', array('border-left-width', 'border-left-style', 'border-left-color'));
			$this->combinarPropiedad($propiedadCombinar, 'border-right', array('border-right-width', 'border-right-style', 'border-right-color'));
			
			$this->combinarPropiedad($propiedadCombinar, 'font', array('font-style', 'font-variant', 'font-weight', 'font-size', 'line-height', 'font-family'));
			$this->combinarPropiedad($propiedadCombinar, 'font', array('font-style', 'font-variant', 'font-weight', 'font-size', 'font-family'));
			$this->combinarPropiedad($propiedadCombinar, 'font', array('font-variant', 'font-weight', 'font-size', 'line-height', 'font-family'));
			$this->combinarPropiedad($propiedadCombinar, 'font', array('font-style', 'font-weight', 'font-size', 'line-height', 'font-family'));
			$this->combinarPropiedad($propiedadCombinar, 'font', array('font-style', 'font-variant', 'font-size', 'line-height', 'font-family'));
			$this->combinarPropiedad($propiedadCombinar, 'font', array('font-variant', 'font-weight', 'font-size', 'font-family'));
			$this->combinarPropiedad($propiedadCombinar, 'font', array('font-style', 'font-weight', 'font-size', 'font-family'));
			$this->combinarPropiedad($propiedadCombinar, 'font', array('font-style', 'font-variant', 'font-size', 'font-family'));
			$this->combinarPropiedad($propiedadCombinar, 'font', array('font-variant', 'font-size', 'font-family'));
			$this->combinarPropiedad($propiedadCombinar, 'font', array('font-weight', 'font-size', 'font-family'));
			$this->combinarPropiedad($propiedadCombinar, 'font', array('font-style', 'font-size', 'font-family'));
		}
		
		protected function combinarPropiedad($objeto, $combinado, $partes) {
			/* separamos las propiedades y valores */
			for ($n = 0; $n < count($objeto); $n++) {
				/* agregamos el tipo a un array */
				$tipoObjeto[] = substr($objeto[$n], 0, strpos($objeto[$n], ':'));
				/* agregamos los valores al array, aunque sea almacenado y no procesado */
				$valoresObjeto[] = substr($objeto[$n], strpos($objeto[$n], ':') + 1, strlen($objeto[$n]));
			}
			/* asumimos que es combinable */
			$combinable = TRUE;
			/* recorremos aunque todas las diferentes propiedades pueden ser combinadas en esta instancia */
			for ($n = 0; $n < count($partes); $n++) {
				/* verificamos si esta propiedad no esta contenida con el array combinable */
				if (!in_array($partes[$n], $tipoObjeto))
					/* no puede ser combinble, asi que almacenamos asi como esta */
					$combinable = FALSE;
			}
			/* si alguna de las propiedades estan en el array combinable */
			if ($combinable) {
				/* recorrer todas las partes */
				for ($a = 0; $a < count($partes); $a++) {
					/* recorrer todas las propiedades que fueron encontradas aqui */
					for ($b = 0; $b < count($tipoObjeto); $b++) {
						/* verificamos si es la misma */
						if ($tipoObjeto[$b] == $partes[$a]) {
							/*
								agregamos el valor actual al valor combinado
								esto debe hacerse en el orden correcto
							*/
							$valoresCombinados[] = $valoresObjeto[$b];
							/* ya no se necesita la propiedad, ya que se agrego a la combinacion, asi que la removemos */
							$objeto[$b] = NULL;
						}
					}
				}
				/* agregamos la nueva propiedad combinada con todos los valores a las propiedades individuales */
				$objeto[] = $combinado . ':' . implode(' ', $valoresCombinados);
			}
		}
		
		protected function eliminarReglasVacias() {
			/* recorremos cada seccion del archivo CSS y verificamos si no contiene propiedades */
			for ($a = 0; $a < count($this->selectores); $a++) {
				/* eliminamos los items en blanco del array */
				$this->propiedades[$a] = array_values(array_diff($this->propiedades[$a], array(NULL)));
				/* verificamos si esta parte no tiene propiedades */
				if (isset($this->propiedades[$a][0]) AND !$this->propiedades[$a][0]) {
					/* removemos la parte vacia de la matriz de propiedades y de los selectores */
					array_splice($this->selectores, $a, 1);
					array_splice($this->propiedades, $a, 1);
					/* disminuimos en uno ya que se disminuyo el total */
					$a--;
				}
			}
		}
		
		protected function combinarReglasIdenticas() {
			/*
				ahora que la hoja de estilos se ha comprimido,
				es utilizado el codigo para combinar las clases identicas
			*/
			/* recorremos todas las reglas */
			for ($a = 0; $a < count($this->propiedades); $a++) {
				/*
					recorremos desde 0 hasta el tamano actual,
					para garantizar que las propiedades procesadas futuramente no sean procesadas prematuramente
				*/
				for ($b = 0; $b < $a; $b++) {
					if (substr($this->selectores[$a][0], 0, 1) <> "@" && substr($this->selectores[$b][0], 0, 1) <> "@") {
						/* verificamos si esta regla es identica a una anterior */
						if (!array_diff($this->propiedades[$a], $this->propiedades[$b]) && !array_diff($this->propiedades[$b], $this->propiedades[$a])) {
							/* combinamos los selectores */
							$this->selectores[$a] = array_unique(array_merge($this->selectores[$a], $this->selectores[$b]));
							/* removemos las propiedades antiguas */
							$this->propiedades[$b] = array(NULL);
							/* removemos los selectores antiguos */
							$this->selectores[$b] = array(NULL);
						}
					}
				}
			}
		}
		
		protected function crearSalida($colores) {
			if ($colores) {
				$this->resultado = '<span style="color:#000;font-family:monospace">';
				for ($a = 0; $a < count($this->selectores); $a++) {
					for ($b = 0; $b < count($this->selectores[$a]); $b++)
						$this->selectores[$a][$b] = '<span style="color:#685">' . $this->selectores[$a][$b] . '</span>';
					for ($b = 0; $b < count($this->propiedades[$a]); $b++) {
						$parts = explode(':', $this->propiedades[$a][$b]);
						$this->propiedades[$a][$b] = '<span style="color:#c86464">' . $parts[0] . '</span>:<span style="color:#369">' . $parts[1] . '</span>';
					}
					$this->resultado .= implode(',', $this->selectores[$a]) . '{';
					$this->resultado .= implode(';', $this->propiedades[$a]) . '}';
				}
				$this->resultado .= '</span>';
			} else {
				for ($a = 0; $a < count($this->selectores); $a++) {
					for ($b = 0; $b < count($this->selectores[$a]); $b++)
						$this->selectores[$a][$b] = $this->selectores[$a][$b];
					for ($b = 0; $b < count($this->propiedades[$a]); $b++) {
						$parts = explode(':', $this->propiedades[$a][$b]);
						$this->propiedades[$a][$b] = '' . $parts[0] . ':' . $parts[1];
					}
					$this->resultado .= implode(',', $this->selectores[$a]) . '{';
					$this->resultado .= implode(';', $this->propiedades[$a]) . '}';
				}
			}
			return $this->resultado;
		}
		
		protected function restaurar2puntos() {
			$this->resultado = str_replace('[!semi-colon!]//', '://', $this->resultado);
			$this->resultado = stripslashes($this->resultado);
		}
		
		protected function eliminarCorchetesVacios() {
			$this->resultado = str_replace("{}","",$this->resultado);
			$this->resultado = str_replace("{;}","",$this->resultado);
			$this->resultado = str_replace("{<br>;<br>}","",$this->resultado);
		}
		
		protected function mostrarResultados() {
			echo '<h1>Estadisticas:</h1><ul>';
			echo '<li>Tama&ntilde;o original: ' . round($this->tamanoInicial / 1024, 2) . ' kB (' . number_format($this->tamanoInicial) . ' B)</li>';
			echo '<li>Tama&ntilde;o final: ' . round(strlen(strip_tags($this->resultado)) / 1024, 2) . ' kB (' . number_format(strlen(strip_tags($this->resultado))) . ' B)</li>';
			echo '<li>Guardado: ' . round(($this->tamanoInicial - strlen(strip_tags($this->resultado))) / 1024, 2) . ' kB (' . number_format(($this->tamanoInicial - strlen(strip_tags($this->resultado)))) . ' B)</li>';
			echo '<li>Reduccion: ' . round(100 - ((strlen(strip_tags($this->resultado)) / $this->tamanoInicial) * 100), 2) . '%</li>';
			echo '</ul>';
			
			$this->tiempoFin = explode(' ', microtime());
			$segundos = $this->tiempoFin[1] - $this->tiempoInicio[1];
			$milisegundos = $this->tiempoFin[0] - $this->tiempoInicio[0];
			$duracion = round($segundos + $milisegundos, 5);
			
			echo '<ul>';
			echo '<li>Durecion: ' . $duracion . ' seconds</li>' ;
			echo '</ul>';
			
			echo '<ul>';
			echo '<li>Reglas: ' . count($this->selectores) . '</li>';
			
			$selectores = 0;
			$propiedades = 0;
			for ($n = 0; $n < count($this->selectores); $n++)
				$selectores += count($this->selectores[$n]);
			for ($n = 0; $n < count($this->propiedades); $n++)
				$propiedades += count($this->propiedades[$n]);
			echo '<li>Selectores: ' . $selectores . '</li>';
			echo '<li>Propiedades: ' . $propiedades . '</li>';
			echo '</ul>';
			echo '<h1>Resultado CSS:</h1>';
		}
	}
	
	function reducirPropiedad(&$valor, $indice) {
		/* reducimos los codigos HEX a mas pequenos, ejemplo: '#FF0000' -> '#F00' */
		reducirHex($valor);
		/*
			reducimos los valores de padding y margins extras
			ejemplo: 'margin: 4px 5px 4px 5px' -> 'margin: 4px 5px'
		*/
		comprimirPaddingMargin($valor);
	}
	
	function reducirHex(&$item) {
		/* verificamos si esta parte tiene algun codigo HEX */
		if (strstr($item, '#')) {
			/* tomamos los seis caracteres siguientes */
			$hex = substr($item, strpos($item, '#')+1, 6);
			/* verificamos si es un codigo hexadecimal */
			if (eregi('[0-9a-f]{6}', $hex)) {
				/* si los caracteres de cada par combinan */
				if ($hex[0] == $hex[1] && $hex[2] == $hex[3] && $hex[4] == $hex[5])
					/* se puede simplificar, por lo que lo modificamos a un hex mas corto */
					$item = eregi_replace('#' . $hex, '#' . $hex[0] . $hex[2] . $hex[4], $item);
			}
		}
	}
	
	function comprimirPaddingMargin(&$item) {
		/*
			aqui eliminados los valores de paddin y margin que no son necesarios
			combinamos las propiedades que pueden ser establecidas en un solo item
			ejemplos:
				- margin-left, margin-top etc.. -> margin: XX
				- padding: 5px 5px 5px 5px -> padding: 5px
				- margin: 2px 4px 2px 4px -> margin: 2px 4px
				- padding: 3px 5px 9px 5px -> padding: 3px 5px 9px
		*/
		/* obtenemos el tipo y el valor de la propiedad */
		$item_parts = explode(':', $item);
		/* verificamos si esta propiedad es padding o margin */
		if ($item_parts[0] == 'padding' || $item_parts[0] == 'margin') {
			/* almacenamos todos los valores al array */
			$values = explode(' ', $item_parts[1]);
			/*
				realizamos diferentes opciones de acuerdo al numero de valores
				no es necesario verificar si es 1 ya que no se puede comprimir
			*/
			switch (count($values)) {
				case 2:
					/* ejemplo: margin: 4px 4px */
					if ($values[0] == $values[1])
						/* ejemplo: margin: 4px */
						array_pop($values);
					break;
				case 3:
					/* ejemplo: margin: 5px 7px 5px */
					if ($values[0] == $values[2]) {
						/* ejemplo: margin: 5px 7px */
						array_pop($values);
						/* ejemplo: margin: 4px 4px */
						if ($values[0] == $values[1])
							/* ejemplo: 4px */
							array_pop($values);
					}
					break;
				case 4:
					/* ejemplo: margin: 3px 7px 9px 7px */
					if ($values[1] == $values[3]) {
						/* ejemplo: 3px 7px 9px */
						array_pop($values);
						/* ejemplo: 3px 4px 3px */
						if ($values[0] == $values[2]) {
							/* ejemplo: 3px 4px */
							array_pop($values);
							/* ejemplo: 7px 7px */
							if ($values[0] == $values[1])
								/* ejemplo: 7px */
								array_pop($values);
						}
					}
					break;
			}
			/* verificamos si los valores se modificaron correctamente */
			if (implode(' ', $values) != $item_parts[1])
				/* si esta correcto, modificamos la matrix con el valor mas corto */
				$item = $item_parts[0] . ':' . implode(' ', $values);
		}
	}
?>